<!DOCTYPE html>
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  
  
  <link rel="shortcut icon" href="../../img/favicon.ico">
  <title>Coroutines - COROS Documentation</title>
  <link rel="stylesheet" href="../../css/theme.css" />
  <link rel="stylesheet" href="../../css/theme_extra.css" />
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/github.min.css" />
  
  <script>
    // Current page data
    var mkdocs_page_name = "Coroutines";
    var mkdocs_page_input_path = "architecture/01_coroutines.md";
    var mkdocs_page_url = null;
  </script>
  
  <script src="../../js/jquery-2.1.1.min.js" defer></script>
  <script src="../../js/modernizr-2.8.3.min.js" defer></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script> 
  
</head>

<body class="wy-body-for-nav" role="document">

  <div class="wy-grid-for-nav">

    
    <nav data-toggle="wy-nav-shift" class="wy-nav-side stickynav">
    <div class="wy-side-scroll">
      <div class="wy-side-nav-search">
        <a href="../.." class="icon icon-home"> COROS Documentation</a>
        <div role="search">
  <form id ="rtd-search-form" class="wy-form" action="../../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" title="Type search term here" />
  </form>
</div>
      </div>

      <div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../..">Home</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">About</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../COPYRIGHT/">Copyright</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../LICENSE/">License</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Beginner's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../tutorials/01_getting_started/">Getting Started</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Hitchker's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../guides/01_coroutines/">Coroutines</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../guides/02_event_queues/">Event Queues</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../guides/03_components/">Components</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Technocrat's Guide to:</span></p>
                <ul>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/01_co/">co.h</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/02_evq/">evq.h</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../../reference/03_comp/">comp.h</a>
                    </li>
                </ul>
                <p class="caption"><span class="caption-text">The Technomancer's Guide to:</span></p>
                <ul class="current">
                    <li class="toctree-l1 current"><a class="reference internal current" href="./">Coroutines</a>
    <ul class="current">
    <li class="toctree-l2"><a class="reference internal" href="#the-basics">The basics</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#the-guts-of-a-coroutine">The guts of a coroutine</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#where-the-co_function-roams">Where the co_function roams</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#the-hairy-stuff">The hairy stuff</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#save-current-state">Save current state</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#swap-the-stack">Swap the stack</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#fiddle-about-with-the-return-value">Fiddle about with the return value</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#pop-the-registers-from-the-new-stack">Pop the registers from the new stack.</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#but-what-about-that-prologue">But what about that prologue?</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#how-its-all-put-together">How it's all put together</a>
        <ul>
    <li class="toctree-l3"><a class="reference internal" href="#yielding">Yielding</a>
    </li>
    <li class="toctree-l3"><a class="reference internal" href="#resuming">Resuming</a>
    </li>
        </ul>
    </li>
    <li class="toctree-l2"><a class="reference internal" href="#summary">Summary</a>
    </li>
    </ul>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../02_event_queues/">Event Queues</a>
                    </li>
                    <li class="toctree-l1"><a class="reference internal" href="../03_porting/">Porting</a>
                    </li>
                </ul>
      </div>
    </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">

      
      <nav class="wy-nav-top" role="navigation" aria-label="top navigation">
        <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
        <a href="../..">COROS Documentation</a>
      </nav>

      
      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="breadcrumbs navigation">
  <ul class="wy-breadcrumbs">
    <li><a href="../..">Docs</a> &raquo;</li>
    
      
        
          <li>The Technomancer's Guide to: &raquo;</li>
        
      
    
    <li>Coroutines</li>
    <li class="wy-breadcrumbs-aside">
      
    </li>
  </ul>
  
  <hr/>
</div>
          <div role="main">
            <div class="section">
              
                <h1 id="the-technomancers-guide-to-coroutines">The Technomancer's Guide to Coroutines</h1>
<p>Coroutines can look like black magic to outside viewers, and as a result can seem both quite intimidating and quite difficult to use until they 'click'.  This document aims to give you the underground view of a coroutine so that the mystery is removed and the process of debugging some of the more mysterious errors you might encounter can be learned.</p>
<h2 id="the-basics">The basics</h2>
<p>The coroutine type and attached implementation function is defined in <code>co.h</code> as follows:</p>
<pre><code class="language-C">typedef struct _co_t *co_t;
typedef void (*co_function)(void *);
</code></pre>
<p>Which is to say that the coroutine is just a structure that you pass around to the various CO functions to let them do their magic.  And that structure is just a wrapper around a central function that takes a void pointer and returns a void pointer.</p>
<p>In the <a href="../../guides/01_coroutines/"><em>Hitchiker's Guide to Coroutines</em></a> this was said:</p>
<blockquote>
<p><em>"A similar routine could be made using just callbacks in the form of an asynch reactor, but such callbacks are infamous for requiring static variables (meaning the same routine can't be used multiple times) or for forcing users to carry around states manually to pass back each time. [...] The code in the coroutine is automatically passing that aforementioned state around without any extra state variables needing to be created and the code style is just linear execution."</em></p>
</blockquote>
<p>The <code>co_t</code> is the structure in which this extra state is passed around.  And unlike the manual state passing approach, the state passing done by a coroutine is <em>generic</em>.  It doesn't matter <em>what</em> state you have, it's kept by the coroutine and when (not if) you change the representation, the representation is automatically updated for you.  And best of all?  It's kept in local variables, not static.</p>
<h3 id="the-guts-of-a-coroutine">The guts of a coroutine</h3>
<pre><code class="language-C">typedef struct _co_t
{
    bool     static_stack;   // stack_store was passed in
    stack_t  *stack_store;   // actual stack array
    stack_t  *stack_pointer; // top of stack
    stack_t  *stack_canary;  // canary location, NULL if not supported
} co_t_impl;
</code></pre>
<p>And here it is: the glory of a... coroutine.</p>
<p>No, really.  That's it.  That's a coroutine.  Four values.  One is a flag that just decides who cleans up the stack: the coroutine (dynamically allocated) or the user (statically allocated).  One is a pointer to the base address of the stack.  One is a pointer showing the current stack pointer location.  And one is a "stack canary" used inside of CO to detect if the coroutine stack has been corrupted.  (This is a limited facility, but in the absence of memory protection it's better than nothing, albeit not perfect.  There is further discussion of this below.)</p>
<p>The more alert readers might note something missing.  "Where's the implementation function?  There's nothing there that's a <code>co_function</code> type!  And they'd be 100% correct.  There isn't.  Because the implementation function is part of the state of a coroutine and the state is held in the stack.  Thus the function address is held ... in the stack.</p>
<p>Magic!</p>
<h3 id="where-the-co_function-roams">Where the <code>co_function</code> roams</h3>
<p>The secret to how this all works can first be found in this function:</p>
<pre><code class="language-C">#define SET_STACK_VAL(OFFSET, VALUE) (stack_buffer[stack_buffer_count - (OFFSET)] = VALUE)
/*...*/
void co_init_impl(stack_t **stack_pointer, stack_t **stack_canary, co_function co_cb,
                  stack_t *stack_buffer, size_t stack_buffer_count)
{
    // check that stack is aligned
    assert((uintptr_t)stack_buffer % 4 == 0);

    // setup stack
    SET_STACK_VAL(1, (uintptr_t)co_prologue_impl); // return to platform prologue
    SET_STACK_VAL(2, 0);                           // r7
    SET_STACK_VAL(3, (uintptr_t)co_halt_impl);     // r6
    SET_STACK_VAL(4, 0xffffffff);                  // r5
    SET_STACK_VAL(5, (uintptr_t)co_cb);            // r4
    SET_STACK_VAL(6, 0);                           // r11
    SET_STACK_VAL(7, 0);                           // r10
    SET_STACK_VAL(8, 0);                           // r9
    SET_STACK_VAL(9, 0);                           // r8

    // setup stack pointer and canary
    *stack_pointer = &amp;stack_buffer[stack_buffer_count - 9];
    *stack_canary = stack_buffer;
}
</code></pre>
<p>This is one of three functions that has to be implemented for each architecture/compiler pairing and it's a doozy!  The example here is for ARM Cortex-M cores with GCC compiler syntax and assuming ARM Thumb1 instructions.</p>
<p>In the process of making a coroutine, what this function does is sets up a stack that mimics what a stack looks like on exiting a subroutine.  The very top of the stack sets up the function <code>co_prolog_impl()</code> as the "return address" of the fake function.  It then pretends to have pushed all the callee-saved registers into the stack: r4 to r11, in the case of the ARM Cortex-M ABI.  The faked out r4 has the implementation function, r5 has a dummy value and is present for future expansion, and r6 is given the address of the function <code>co_halt_impl()</code>.  (Why R4 for the <code>co_function</code> and R6 for the <code>co_halt_impl()?</code>  Whimsy.  They have to be in the callee-saved registers, and I just started from the first of them.)</p>
<blockquote>
<p><em><strong>A note on some ABI terminology:</strong> In any ABI the question of what to do with the contents of registers when making a subroutine call has to be answered.  In the case of the ARM ABI for Cortex-M devices (among others) the answer is this: registers R4-R11 are "callee-saved" must be preserved by the called routine.  If the called routine ("callee") makes any use of any of these registers, it </em>must<em> store them somewhere before use, and must restore them before returning to the caller.  Registers R0-R3 and R12 are "caller-saved".  The called function may alter them at will without regard for the caller.  If the caller needs certain values in them preserved, it it up to the caller to store them before calling and restoring them after calling.  CO is written to conform to the various ABIs of its target so that means storing all the callee-saved registers and ignoring the caller-saved.  (This is an important contrast to pre-emptive tasking systems which must save </em>all<em> register state on a task change.)</em></p>
</blockquote>
<p>What this means is that when the coroutine is resumed, it will "return" to <code>co_prolog_impl()</code> with the other values at known locations in the stack.  This also means that the <code>co_function</code> we passed into the coroutine creation also resides on the stack or in registers.</p>
<p>When I said that the state carriage was generic, I meant it.  Any set of values that can fit in your stack (including arbitrary depths of stack frames, which is what makes CO "stackful" as per the Hitchhiker's Guide) can be carried around by the co_t, even though the co_t itself only occupies the space of four words.</p>
<h2 id="the-hairy-stuff">The hairy stuff</h2>
<p>Now that we understand that states are passed around in a simulated stack, we need to understand how resuming and yielding work.  That's actually a trick question.  Because of the way <code>co_create()</code> works, calling <code>co_init_impl()</code> above, there is no difference internally between "resuming" and "yielding" a coroutine.  Internally it's all the same mechanism and it all boils down, in the end, to a call to:</p>
<pre><code class="language-C">__attribute__((naked)) void *co_yield_impl(stack_t **stack_pointer, void *data)
{
    UNUSED(stack_pointer);
    UNUSED(data);
    __asm volatile(
        &quot;    push {r4,r5,r6,r7,lr} \n&quot; // push callee saved registers
        &quot;    mov r4, r8            \n&quot; // yes we need these moves, thumb1 can
        &quot;    mov r5, r9            \n&quot; // only push r0-r7 at the same time
        &quot;    mov r6, r10           \n&quot;
        &quot;    mov r7, r11           \n&quot;
        &quot;    push {r4,r5,r6,r7}    \n&quot;
        &quot;    mov r2, sp            \n&quot; // swap stack, takes several instructions
        &quot;    ldr r3, [r0]          \n&quot; // here because thumb1 can't load/store sp
        &quot;    str r2, [r0]          \n&quot;
        &quot;    mov sp, r3            \n&quot;
        &quot;    mov r0, r1            \n&quot; // return arg
        &quot;    pop {r4,r5,r6,r7}     \n&quot; // pop callee saved registers and return
        &quot;    mov r8, r4            \n&quot;
        &quot;    mov r9, r5            \n&quot;
        &quot;    mov r10, r6           \n&quot;
        &quot;    mov r11, r7           \n&quot;
        &quot;    pop {r4,r5,r6,r7,pc}  \n&quot;
    );
    // We have done the return manually in assembler.
}
</code></pre>
<p>This is the core of the coroutine, where the state gets swapped.  (Again this is for Cortex-M/GCC.  Other cores and compilers will look different.)  It looks mysterious, especially if you're uncomfortable with assembly languages.  It really is, however, a simple 4-step process:</p>
<ol>
<li>Save the callee-saved registers and the return address into the stack.</li>
<li>Swap the stacks.</li>
<li>Fiddle the return value into place.</li>
<li>Pop the callee-saved registers and the program counter from the stack.</li>
</ol>
<h3 id="save-current-state">Save current state</h3>
<p>Saving the current state is this code:</p>
<pre><code class="language-C">        &quot;    push {r4,r5,r6,r7,lr} \n&quot;
        &quot;    mov r4, r8            \n&quot;
        &quot;    mov r5, r9            \n&quot;
        &quot;    mov r6, r10           \n&quot;
        &quot;    mov r7, r11           \n&quot;
        &quot;    push {r4,r5,r6,r7}    \n&quot;
</code></pre>
<p>We just save the callee-saved registers as required by the ARM ABI.  In this case we use a less elegant approach than Thumb2 permits because we want to support <strong>all</strong> Thumb-capable devices, not just the Thumb2-capable.  The trade-off here is more clunky code and a very slight overhead (on the order of maybe four clock cycles) in execution speed in exchange for code universality across all Thumb-capable devices.  Should a Thumb2-specific routine be desired, adding it would be a simple application of the instructions in <a href="../03_porting/"><em>The Technomancer's Guide to Porting COROS</em></a> followed by testing the system via the test suite.</p>
<h3 id="swap-the-stack">Swap the stack</h3>
<pre><code class="language-C">        &quot;    mov r2, sp            \n&quot;
        &quot;    ldr r3, [r0]          \n&quot;
        &quot;    str r2, [r0]          \n&quot;
        &quot;    mov sp, r3            \n&quot;
</code></pre>
<p>Again this is a bit more involved than it has to be in Thumb2 machines, but not by much.  Se store the current stack pointer in R2.  We then load R3 from the passed-in stack pointer (R0 contains a <code>stack_t **</code> which is a pointer to the <code>stack_pointer</code> member of <code>co_t_impl</code>).  The value we just put into R2 then gets stored in that very same place, after which we move the new stack pointer from R3.</p>
<p>It is key to understand that we are now pointing to a completely different stack!  The first time a coroutine is resumed, that stack is the one we built up above in <code>co_init_impl()</code>.  Afterwards it is whatever the ongoing computations of the coroutine leaves on the stack, plus its current CPU state (callee-saved registers only).</p>
<h3 id="fiddle-about-with-the-return-value">Fiddle about with the return value</h3>
<pre><code class="language-C">        &quot;    mov r0, r1            \n&quot;
</code></pre>
<p>Remember that <code>co_resume()</code> and <code>co_yield()</code> both have reflecting parameters and return values.  The data passed to <code>co_resume()</code> is the return value of <code>co_yield()</code>; the data passed to <code>co_yield()</code> is the return value of <code>co_resume()</code>.  In this implementation function the data is the second parameter and thus, by ARM ABI rules, is stored in R1.  To make this the return value we follow the ARM ABI and move it to R0.</p>
<h3 id="pop-the-registers-from-the-new-stack">Pop the registers from the new stack.</h3>
<p>And here is the final step of the deep magic:</p>
<pre><code class="language-C">        &quot;    pop {r4,r5,r6,r7}     \n&quot;
        &quot;    mov r8, r4            \n&quot;
        &quot;    mov r9, r5            \n&quot;
        &quot;    mov r10, r6           \n&quot;
        &quot;    mov r11, r7           \n&quot;
        &quot;    pop {r4,r5,r6,r7,pc}  \n&quot;
</code></pre>
<p>Here we pop all the registers in reverse order of how we pushed them.  (There is one exception you may have spotted; this will be explained below.)</p>
<p>So again because of Thumb1 this is a two-stage process.  First we pop 4 value into R4-R7.  These we immediately move into R8-R11.  Then we pop four more values into R4-R7 which we keep and, as well, we pop a fifth value into ... PC.  The program counter.</p>
<p>This is an artifact of how ARM (and most RISC chips) do "calls".  In brief, you "call" by using <code>bl &lt;address&gt;</code> which puts the next instruction after the current PC into the LR register before branching, and then you return by either directly calling <code>bx lr</code> or, more commonly in stack-oriented languages, by pushing the LR on entry and popping into the PC on exit.  This is very different from how CISC architectures tend to do things where the return address is pushed onto a hardware-managed stack on call instructions and popped from the same stack on return instructions.</p>
<p>But all of this is unimportant because COROS is neutral in this regard.  It calls an implementation function that does all the required ABI magic for it.  Should, say, an x86 port be required, the x86 version of this function would use <code>call</code>/<code>ret</code> logic instead of <code>bl</code>/<code>bx</code> logic.</p>
<p>The practical upshot of all of this, however, is that when this function is called (by higher-level functions in CO we will look at later), we will have performed a full context switch.  We will be in a new routine with its own isolated state and ready to continue processing in that new routine without any higher-level code being any the wiser.</p>
<h3 id="but-what-about-that-prologue">But what about that prologue?</h3>
<p>The <code>co_init_impl()</code> function set up a <code>co_prologue_impl()</code> function in the LR slot.  This means that when that coroutine is first yielded to the PC will be starting at that routine.  What is that routine and why does it exist?</p>
<p>An "obvious" implementation of <code>co_init_impl()</code> would have put the <code>co_function</code> parameter into the LR position so that this function would be the one called when control was transferred.  (Indeed early revisions of COROS did just that.)  And this works fine ... until the <code>co_function</code> backing the coroutine exits.  If it ever does it will underflow its stack and branch off into Neverland to do damnable violence to your lovely code.  No, we need to put something safer there.  And that safer thing is this:</p>
<pre><code class="language-C">__attribute__((naked)) void co_prologue_impl(void)
{
    __asm volatile(
        &quot;    mov lr, r6 \n&quot;
        &quot;    bx r4      \n&quot;
    );
}
</code></pre>
<p>Remember how the <code>co_function</code> (<code>co_cb()</code>) was stored in R4's slot?  And how a function called <code>co_halt_impl()</code> was stored in the R6 slot?  We exploit this fact to switch LR to <code>co_halt_impl()</code> (an architecture-independent C function) before we do a straight branch (no link) to the contents of R4 (the <code>co_function</code> implementation).</p>
<p>Now we have a stack frame that is safe.  The coroutine can run, do whatever it likes, and it can even return safely.  When it returns, the system doesn't explode violently with razor-sharp shards of code and pointers massacring our SRAM.  Instead we "return" to this function:</p>
<pre><code class="language-C">void co_halt_impl(void)
{
    while (true)
    {
        co_yield_impl(&amp;co_active-&gt;stack_pointer, NULL);
    }
}
</code></pre>
<p><code>co_active</code> is just a variable that stores the active coroutine at the time of resuming.  So on exit from a coroutine, the coroutine yields to whatever the active coroutine was that resumed it, returning NULL.  Being inside an endless loop, any time it is resumed again, it will just immediately yield returning NULL.  In this way a coroutine fails safe instead of destroying your system with undiagnosable memory errors.  (This is a highly-desired feature in an embedded system.)</p>
<h2 id="how-its-all-put-together">How it's all put together</h2>
<p>What we've covered so far is the low-level implementation details of how context shifts occur.  What we've only briefly touched upon at all is how this is all wrangled at the top end.  For example while <code>co_resume()</code> and <code>co_yield()</code> all in the end wind up calling <code>co_yield_impl()</code> there is a clear difference between resuming and yielding.  How is this expressed in CO?</p>
<h3 id="yielding">Yielding</h3>
<p>This is the implementation of yielding:</p>
<pre><code class="language-C">void *co_yield(void *data)
{
    // Permit coroutine-based code to work in non-coroutine environments.
    if (!co_active)
    {
        return NULL;
    }

    // check canary, if this fails a stack overflow occured
    assert(!co_active-&gt;stack_canary || *co_active-&gt;stack_canary == (stack_t)STACK_CANARY_VALUE);

    // yield out of coroutine
    return co_yield_impl(&amp;co_active-&gt;stack_pointer, data);
}
</code></pre>
<p>It's a very simple function.  First it checks if there's an active coroutine at all.  If there isn't it simulates a coroutine that yielded NULL.  This permits coroutine-based code to work in non-coroutine environments (at least in a degraded fashion).</p>
<p>Next we check the mysterious "stack canary" we mentioned above.  If the active coroutine has a stack canary (currently all coroutines do, but this is not necessary and future versions may have unprotected and protected coroutines) it confirms that the stack canary has not changed its value.  If the value has changed, the assertion faults.  Note that this is a call to <code>assert()</code> and thus will not execute in production code.  The cost of checking the stack canary is there for confirming behaviour in, presumably, comprehensive tests, but not in code meant to be run for real.</p>
<p>Finally, it calls <code>co_yield_impl()</code> using the active coroutine's stack and the passed-in data.  From there we know what happens from our exhaustive description above.  (Or something similar for other architectures.)</p>
<blockquote>
<p><em><strong>A brief note on stack canaries:</strong> It should be noted that stack canaries are very limited constructs.  They can only signal some errors (if your stack references jump past the canary without altering it, for example, the canary sings happily anyway).  They can only tell you of an error long after it has transpired.  They're sort of a last-ditch mechanism and in MCUs, because of the lack of detailed memory protections, and the lack of the ability to grow stacks on demand, they cannot be relied upon.  They're one tool for stack protection, but an imperfect one.</em></p>
</blockquote>
<h3 id="resuming">Resuming</h3>
<p>Resuming a coroutine is only slightly more complex:</p>
<pre><code class="language-C">void *co_resume(co_t co, void *data)
{
    void *rv;

    if (co_active == co)
    {
        rv = NULL;
    }
    else
    {
        // push previous coroutine's info on the current stack
        co_t co_previous = co_active;
        co_active = co;

        // yield into coroutine
        rv = co_yield_impl(&amp;co-&gt;stack_pointer, data);

        // restore previous coroutine's info
        co_active = co_previous;
    }

    return rv;
}
</code></pre>
<p>First we check if we somehow resumed ourself.  If we have, we stop processing and return NULL, letting ourselves, in effect, continue; coroutines cannot resume themselves (though they could resume another coroutine backed by the same implementation function!).</p>
<p>If we are not resuming ourselves, we store the active coroutine into our own stack (local variable) and set the new coroutine as the active one.  We then yield, again using the mechanism we discussed at length, into the new coroutine.  When that coroutine yields back to us, we store the return value and restore the previous coroutine as the active one.  We then return the value.</p>
<h2 id="summary">Summary</h2>
<p>And that's it.  That's the "deep magic" of coroutines.  A coroutine is just a subroutine that carries its own stack and thus carries around its full state.  Switching coroutines just involves saving the current coroutine's registers into its stack, switching the stack to a new coroutine's, then restoring that coroutine's register state.  This one simple trick allows for more straightforward linear programming logic without any need for the complexity of locks and signals and such that plague pre-emptive systems.</p>
              
            </div>
          </div>
          <footer>
  
    <div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
      
        <a href="../02_event_queues/" class="btn btn-neutral float-right" title="Event Queues">Next <span class="icon icon-circle-arrow-right"></span></a>
      
      
        <a href="../../reference/03_comp/" class="btn btn-neutral" title="comp.h"><span class="icon icon-circle-arrow-left"></span> Previous</a>
      
    </div>
  

  <hr/>

  <div role="contentinfo">
    <!-- Copyright etc -->
    
  </div>

  Built with <a href="https://www.mkdocs.org/">MkDocs</a> using a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
      
        </div>
      </div>

    </section>

  </div>

  <div class="rst-versions" role="note" aria-label="versions">
    <span class="rst-current-version" data-toggle="rst-current-version">
      
      
        <span><a href="../../reference/03_comp/" style="color: #fcfcfc;">&laquo; Previous</a></span>
      
      
        <span style="margin-left: 15px"><a href="../02_event_queues/" style="color: #fcfcfc">Next &raquo;</a></span>
      
    </span>
</div>
    <script>var base_url = '../..';</script>
    <script src="../../js/theme.js" defer></script>
      <script src="../../search/main.js" defer></script>
    <script defer>
        window.onload = function () {
            SphinxRtdTheme.Navigation.enable(true);
        };
    </script>

</body>
</html>
